/**
 * ReportGear(2011)
 */
package com.reportgear.report.model.cell;

import org.dom4j.Element;

import com.reportgear.core.api.XmlSerializer;
import com.reportgear.report.model.cell.style.Style;
import com.reportgear.report.model.cell.value.AbstractCellObject;
import com.reportgear.report.model.cell.value.ModelDesignableValueObjectClassManager;
import com.sot.core.util.NumberUtils;
import com.sot.core.util.StringUtils;

/**
 * 抽象Cell单元格
 * 
 * @version 1.0 2011-3-9
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public abstract class AbstractCell implements Cell {
	// 列
	private int column = -1;
	// 行
	private int row = -1;
	// 列跨度
	private int columnSpan = 1;
	// 行跨度
	private int rowSpan = 1;
	// 值
	private Object value;
	// 样式
	private Style style;
	// 合并到单元格
	private CR mergedToCR;
	// 是否合并
	private boolean merged;

	/**
	 * x 构造函数
	 * 
	 * @param column
	 *            列
	 * @param row
	 *            行
	 */
	public AbstractCell(int column, int row) {
		this.column = column;
		this.row = row;
	}

	@Override
	public int getColumn() {
		return this.column;
	}

	@Override
	public int getColumnSpan() {
		return this.columnSpan;
	}

	@Override
	public int getRow() {
		return this.row;
	}

	@Override
	public int getRowSpan() {
		return this.rowSpan;
	}

	@Override
	public void setColumn(int column) {
		this.column = column;
	}

	@Override
	public void setColumnSpan(int columnSpan) {
		this.columnSpan = columnSpan;
	}

	@Override
	public void setRow(int row) {
		this.row = row;
	}

	@Override
	public void setRowSpan(int rowSpan) {
		this.rowSpan = rowSpan;
	}

	@Override
	public Object getValue() {
		return value;
	}

	@Override
	public void setValue(Object value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return String.format("列:%s,行:%s", this.column, this.row);
	}

	@Override
	public boolean isEmpty() {
		if ((this.value == null) || (StringUtils.isEmpty(value))) {
			return true;
		}

		return false;
	}

	@Override
	public void clear() {
		this.value = null;
	}

	@Override
	public void setStyle(Style style) {
		this.style = style;
	}

	@Override
	public Style getStyle() {
		return this.style == null ? Style.DEFAULT_STYLE : this.style;
	}

	@Override
	public boolean isMerged() {
		return this.merged;
	}

	@Override
	public void setMerged(boolean merged) {
		this.merged = merged;
	}

	@Override
	public void mergeIntoCell(int column, int row) {
		this.mergedToCR = new CR(column, row);
	}

	@Override
	public CR getMergedToCR() {
		return this.mergedToCR;
	}

	/**
	 * @return 克隆对象
	 */
	public abstract AbstractCell clone();

	@Override
	public void read(Element parent) {
		this.setColumnSpan(NumberUtils.convertToInteger(parent.attributeValue("cs")));
		this.setRowSpan(NumberUtils.convertToInteger(parent.attributeValue("rs")));

		Element el = parent.element("value");
		String clazzKey = el.attributeValue("class");
		if (!StringUtils.isEmpty(clazzKey)) {
			this.readCellValue(el, clazzKey);
		}
	}

	private void readCellValue(Element el, String clazzKey) {
		try {
			Class<?> clazz = ModelDesignableValueObjectClassManager.INSTANCE.getKeyClass(clazzKey);

			// 如果是字符串
			if (clazz.isAssignableFrom(String.class)) {
				this.setValue(el.getTextTrim());
			} else if (AbstractCellObject.class.isAssignableFrom(clazz)) {
				AbstractCellObject bo = (AbstractCellObject) clazz.newInstance();
				bo.read(el);
				this.setValue(bo);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void write(Element parent) {
		parent.addAttribute("c", "" + this.column);
		parent.addAttribute("r", "" + this.row);
		parent.addAttribute("cs", "" + this.columnSpan);
		parent.addAttribute("rs", "" + this.rowSpan);

		Element v = parent.addElement("value");
		if (value instanceof XmlSerializer) {
			((XmlSerializer) value).write(v);
		} else if (value instanceof String) {
			v.addAttribute("class", ModelDesignableValueObjectClassManager.INSTANCE.getClassKey(String.class));

			v.addText(String.valueOf(value));
		}
	}
}
